//
// Created on 2024/4/24.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#include "Transformer.h"
#include "models/NativeObject.h"

namespace rcim {
namespace trans {
const char *unProgressCharPtr = nullptr;
const std::string unProgressString = "";
const napi_value unProgressValue = nullptr;

// 基本数据类型转换 ******************************************************************
std::string stringFromValue(napi_env env, napi_value value) {
    size_t length = 0;
    napi_get_value_string_utf8(env, value, nullptr, 0, &length);
    std::string ret_str(length, '\0');
    napi_get_value_string_utf8(env, value, (char *)ret_str.data(), length + 1, &length);
    return ret_str;
}

// 调用此方法需要释放
const char *charFromStringByMallocSafety(std::string str) {
    if (str.empty()) {
        return unProgressCharPtr;
    }
    size_t len = str.length();
    char *c_char_ptr = (char *)malloc(len + 1);
    if (c_char_ptr == nullptr) {
        return unProgressCharPtr;
    }
    std::strcpy(c_char_ptr, str.c_str());
    return c_char_ptr;
}

std::string charToStringFromSafety(const char *char_ptr) {
    if (char_ptr == nullptr) {
        return unProgressString;
    }
    try {
        return std::string(char_ptr);
    } catch (const std::exception &e) {
        return unProgressString;
    }
}

napi_value stringToValue(napi_env env, std::string str) {
    if (str.empty()) {
        return unProgressValue;
    }
    napi_value ret;
    napi_create_string_utf8(env, str.c_str(), str.length(), &ret);
    return ret;
}

void setPropertyString(napi_env env, napi_value obj, std::string k, std::string v) {
    if (k.empty()) {
        k = unProgressString;
    }
    if (v.empty()) {
        v = unProgressString;
    }
    napi_value key = stringToValue(env, k);
    napi_value value = stringToValue(env, v);
    napi_set_property(env, obj, key, value);
}

std::string getPropertyString(napi_env env, napi_value obj, std::string k) {
    if (k.empty()) {
        return unProgressString;
    }
    napi_value key = stringToValue(env, k);
    napi_value value;
    napi_get_property(env, obj, key, &value);
    return stringFromValue(env, value);
}

napi_value getPropertyObject(napi_env env, napi_value obj, std::string k) {
    if (k.empty()) {
        return nullptr;
    }
    napi_value key = stringToValue(env, k);
    napi_value value;
    napi_get_property(env, obj, key, &value);
    return value;
}

int32_t int32FromValue(napi_env env, napi_value value) {
    int32_t ret;
    napi_get_value_int32(env, value, &ret);
    return ret;
}

napi_value int32ToValue(napi_env env, int32_t num) {
    napi_value ret;
    napi_create_int32(env, num, &ret);
    return ret;
}


void setPropertyInt32(napi_env env, napi_value obj, std::string k, int32_t v) {
    if (env == nullptr || obj == nullptr) {
        return;
    }
    if (k.empty()) {
        k = unProgressString;
    }
    napi_value key = stringToValue(env, k);
    napi_value value = int32ToValue(env, v);
    napi_set_property(env, obj, key, value);
}

int32_t getPropertyInt32(napi_env env, napi_value obj, std::string k) {
    if (k.empty()) {
        k = unProgressString;
    }
    napi_value key = stringToValue(env, k);
    napi_value value;
    napi_get_property(env, obj, key, &value);
    return int32FromValue(env, value);
}

int64_t int64FromValue(napi_env env, napi_value value) {
    int64_t ret;
    napi_get_value_int64(env, value, &ret);
    return ret;
}

napi_value int64ToValue(napi_env env, int64_t num) {
    napi_value ret;
    napi_create_int64(env, num, &ret);
    return ret;
}

void setPropertyInt64(napi_env env, napi_value obj, std::string k, int64_t v) {
    if (k.empty()) {
        k = unProgressString;
    }
    napi_value key = stringToValue(env, k);
    napi_value value = int64ToValue(env, v);
    napi_set_property(env, obj, key, value);
}

int64_t getPropertyInt64(napi_env env, napi_value obj, std::string k) {
    if (k.empty()) {
        k = unProgressString;
    }
    napi_value key = stringToValue(env, k);
    napi_value value;
    napi_get_property(env, obj, key, &value);
    return int64FromValue(env, value);
}

bool boolFromValue(napi_env env, napi_value value) {
    bool ret;
    napi_get_value_bool(env, value, &ret);
    return ret;
}
napi_value boolToValue(napi_env env, bool num) {
    napi_value ret;
    napi_get_boolean(env, num, &ret);
    return ret;
}

void setPropertyBool(napi_env env, napi_value obj, std::string k, bool v) {
    if (k.empty()) {
        k = unProgressString;
    }
    napi_value key = stringToValue(env, k);
    napi_value value = boolToValue(env, v);
    napi_set_property(env, obj, key, value);
}

bool getPropertyBool(napi_env env, napi_value obj, std::string k) {
    if (k.empty()) {
        k = unProgressString;
    }
    napi_value key = stringToValue(env, k);
    napi_value value;
    napi_get_property(env, obj, key, &value);
    return boolFromValue(env, value);
}

void setPropertyObject(napi_env env, napi_value obj, std::string k, NativeObject *nativeObj) {
    if (k.empty()) {
        k = unProgressString;
    }
    napi_value key = stringToValue(env, k);
    if (nativeObj == nullptr) {
        napi_set_property(env, obj, key, nullptr);
    } else {
        napi_set_property(env, obj, key, nativeObj->toValue(env));
    }
}

bool isValidValue(napi_env env, napi_value obj) {
    if (env == nullptr || obj == nullptr) {
        return false;
    }
    napi_valuetype result;
    napi_typeof(env, obj, &result);
    if (napi_undefined == result || napi_null == result) {
        return false;
    }
    return true;
}

bool isInvalidValue(napi_env env, napi_value obj) { return !isValidValue(env, obj); }

} // namespace trans
} // namespace rcim